﻿using System.Collections.Generic;
using Castle.DynamicProxy;
using RrslLite.Net.Messages;

namespace RrslLite.Net.Aop
{
    public abstract class InterceptorBase<TTarget> : IInterceptor
    {
        private Message _message;

        public InterceptorBase(Message message)
        {
            _message = message;
        }
        
        #region IInterceptor Members

        public virtual void Intercept(IInvocation invocation)
        {
            _message.OperationContainerName = GetOperationContainerName();
            _message.OperationName = invocation.Method.Name;
            _message.OperationParameters = GetParametersDictionary(invocation);

            ProcessMessage(_message, invocation);
        }

        #endregion

        protected abstract void ProcessMessage(Message message, IInvocation invocation);

        protected Dictionary<string, object> GetParametersDictionary(IInvocation invocation)
        {
            var result = new Dictionary<string, object>();

            for (int index = 0; index < invocation.Method.GetParameters().Length; index++)
            {
                var parameterInfo = invocation.Method.GetParameters()[index];
                
                var actualArgument = invocation.Arguments[index];

                foreach (var msgReceiveInterceptor in RrslLite.Configuration.RrslLiteConfiguration.Instance.BatchBuilderConfiguration.EntityAopProxyGeneratorConfiguration.MessageReceiveInterceptors)
                {
                    if (msgReceiveInterceptor.MessageSendProcess == null)
                    {
                        continue;
                    }

                    actualArgument = msgReceiveInterceptor.MessageSendProcess(actualArgument);
                }

                result.Add(parameterInfo.Name, actualArgument);
            }

            return result;
        }

        protected string GetOperationContainerName()
        {
            var genericType = typeof(TTarget);

            var result = genericType.Name;

			//if (genericType.IsInterface)
			//    result = result.TrimStart('I', 'i');

            return result;
        }
    }
}
